#include "regressionanalysis.h"
#include <QFile>
#include <QtCore>

RegressionAnalysis::RegressionAnalysis() {

}

void RegressionAnalysis::setStockData(Stock *stockData) {
    stock = stockData;
    QList<QHash<QString, QString> > fileData = stock->fileData;
    QList<QHash<QString, QString> > predictorData = stock->predictorData;
    QDateTime constant = QDateTime::fromString(fileData.at(0).value("time"), "yyyy-MM-dd HH:mm:ss");
    QTime time(0, 0, 0, 0);
    constant.setTime(time);
    qint64 xValue = 0;float yValue = 0.0;
    for (int i=0; i< fileData.size();i++) {
        QString timeString = fileData.at(i).value("time");
        QDateTime current = QDateTime::fromString(timeString, "yyyy-MM-dd HH:mm:ss");
        xValue += (current.toMSecsSinceEpoch() - constant.toMSecsSinceEpoch());
        QString priceString = fileData.at(i).value("price");
        yValue += priceString.toFloat();
    }
    for (int i=0;i< predictorData.size();i++) {
        QString timeString = predictorData.at(i).value("time");
        QDateTime current = QDateTime::fromString(timeString, "yyyy-MM-dd HH:mm:ss");
        xValue += (current.toMSecsSinceEpoch() - constant.toMSecsSinceEpoch());
        QString priceString = predictorData.at(i).value("price");
        yValue += priceString.toFloat();
    }
    if (predictorData.size() > 0) {
        xValue = (xValue / (fileData.size()+predictorData.size()));
        yValue = (yValue / (fileData.size()+predictorData.size()));
    }
    else {
        xValue = (xValue / fileData.size());
        yValue = (yValue / fileData.size());
    }

    this->setCalculateXmean(QString::number(xValue));
    this->setCalculateYmean(QString::number(yValue));
    this->calculateDeviationX(stock, this->getCalculateXmean());
    this->calculateDeviationY(stock, this->getCalculateYmean());
    this->calculateSquareDeviationX(this->getDeviationX());
    this->calculateSquareDeviationY(this->getDeviationY());
    this->calculateDeviationXY(this->getDeviationX(), this->getDeviationY());
    this->calculateSumSquareDeviationX(this->getSquareDeviationX());
    this->calculateSumSquareDeviationY(this->getSquareDeviationY());
    this->calculateSumDeviationXY(this->getDeviationXY());
    double b1 = (this->getSumDeviationXY().toDouble() / this->getSumSquareDeviationX().toDouble());
    double b0 = (this->getCalculateYmean().toDouble() - (b1*this->getCalculateXmean().toDouble()));
    this->setB1(QString::number(b1));
    this->setB0(QString::number(b0));
}

void RegressionAnalysis::setCalculateXmean(QString cXmean){
    calculateXmean = cXmean;
}

QString RegressionAnalysis::getCalculateXmean() {
    return calculateXmean;
}

void RegressionAnalysis::setCalculateYmean(QString cYmean){
    calculateYmean = cYmean;
}

QString RegressionAnalysis::getCalculateYmean() {
    return calculateYmean;
}

void RegressionAnalysis::calculateDeviationX(Stock *stockData, QString cXmean) {
    QHash<qint16, qint64> xData;
    QDateTime constant = QDateTime::fromString(stockData->fileData.at(0).value("time"), "yyyy-MM-dd HH:mm:ss");
    QTime time(0, 0, 0, 0);
    constant.setTime(time);
    int counter = 0;
    for (int i=0; i< stockData->fileData.size();i++) {
        QString timeString = stockData->fileData.at(i).value("time");
        QDateTime current = QDateTime::fromString(timeString, "yyyy-MM-dd HH:mm:ss");
        xData.insert(counter, ((current.toMSecsSinceEpoch() - constant.toMSecsSinceEpoch()) - cXmean.toLongLong()));
        counter++;
    }
    for (int i=0;i< stockData->predictorData.size();i++) {
        QString timeString = stockData->predictorData.at(i).value("time");
        QDateTime current = QDateTime::fromString(timeString, "yyyy-MM-dd HH:mm:ss");
        xData.insert(counter, ((current.toMSecsSinceEpoch() - constant.toMSecsSinceEpoch()) - cXmean.toLongLong()));
        counter++;
    }
    this->setDeviationX(xData);
}

void RegressionAnalysis::setDeviationX(QHash<qint16, qint64> xData) {
    deviationX = xData;
}

QHash<qint16, qint64> RegressionAnalysis::getDeviationX() {
    return deviationX;
}

void RegressionAnalysis::calculateDeviationY(Stock *stockData, QString cYmean) {
    QHash<qint16, qint64> yData;
    double meanPrice = cYmean.toDouble();
    int counter = 0;
    for (int i=0; i< stockData->fileData.size();i++) {
        QString priceString = stockData->fileData.at(i).value("price");
        yData.insert(counter, (priceString.toDouble() - meanPrice));
        counter++;
    }
    for (int i=0;i< stockData->predictorData.size();i++) {
        QString priceString = stockData->predictorData.at(i).value("price");
        yData.insert(counter, (priceString.toDouble() - meanPrice));
        counter++;
    }
    this->setDeviationY(yData);
}

void RegressionAnalysis::setDeviationY(QHash<qint16, qint64> yData) {
    deviationY = yData;
}

QHash<qint16, qint64> RegressionAnalysis::getDeviationY() {
    return deviationY;
}

void RegressionAnalysis:: calculateSquareDeviationX(QHash<qint16, qint64> devX) {
    QHash<qint16, qint64> data;
    QHashIterator<qint16, qint64> it(devX);
    while(it.hasNext()) {
        it.next();
        data.insert(it.key(), (it.value() * it.value()));
    }

    this->setSquareDeviationX(data);
}

void RegressionAnalysis::setSquareDeviationX(QHash<qint16, qint64> squareDX) {
    squareDeviationX = squareDX;
}

QHash<qint16, qint64> RegressionAnalysis::getSquareDeviationX() {
    return squareDeviationX;
}

void RegressionAnalysis:: calculateSquareDeviationY(QHash<qint16, qint64> devY) {
    QHash<qint16, qint64> data;
    QHashIterator<qint16, qint64> it(devY);
    while(it.hasNext()) {
        it.next();
        data.insert(it.key(), (it.value() * it.value()));
    }

    this->setSquareDeviationY(data);
}

void RegressionAnalysis::setSquareDeviationY(QHash<qint16, qint64> squareDY) {
    squareDeviationY = squareDY;
}

QHash<qint16, qint64> RegressionAnalysis::getSquareDeviationY() {
    return squareDeviationY;
}

void RegressionAnalysis::calculateDeviationXY(QHash<qint16, qint64> xData, QHash<qint16, qint64> yData) {
    QHash<qint16, qint64> data;
    QHashIterator<qint16, qint64> it1(xData);QHashIterator<qint16, qint64> it2(yData);
    while(it1.hasNext()) {
        it1.next();it2.next();
        data.insert(it1.key(), (it1.value() * it2.value()));
    }

    this->setDeviationXY(data);
}

void RegressionAnalysis::setDeviationXY(QHash<qint16, qint64> dataXY) {
    deviationXY = dataXY;
}

QHash<qint16, qint64> RegressionAnalysis::getDeviationXY() {
    return deviationXY;
}

QString RegressionAnalysis::calculateSumSquareDeviationX(QHash<qint16, qint64> xData) {
    qint64 data = 0;
    QHashIterator<qint16, qint64> it(xData);
    while(it.hasNext()) {
        it.next();
        data += it.value();
    }
    this->setSumSquareDeviationX(QString::number(data));
    return QString::number(data);
}

void RegressionAnalysis::setSumSquareDeviationX(QString xData) {
    sumSquareDeviationX = xData;
}

QString RegressionAnalysis::getSumSquareDeviationX() {
    return sumSquareDeviationX;
}

QString RegressionAnalysis::calculateSumSquareDeviationY(QHash<qint16, qint64> yData) {
    qint64 data = 0;
    QHashIterator<qint16, qint64> it(yData);
    while(it.hasNext()) {
        it.next();
        data += it.value();
    }
    this->setSumSquareDeviationY(QString::number(data));
    return QString::number(data);
}

void RegressionAnalysis::setSumSquareDeviationY(QString yData) {
    sumSquareDeviationY = yData;
}

QString RegressionAnalysis::getSumSquareDeviationY() {
    return sumSquareDeviationY;
}

QString RegressionAnalysis::calculateSumDeviationXY(QHash<qint16, qint64> xyData) {
    qint64 data = 0;
    QHashIterator<qint16, qint64> it(xyData);
    while(it.hasNext()) {
        it.next();
        data += it.value();
    }
    this->setSumDeviationXY(QString::number(data));
    return QString::number(data);
}

void RegressionAnalysis::setSumDeviationXY(QString xyData) {
    sumDeviationXY = xyData;
}

QString RegressionAnalysis::getSumDeviationXY() {
    return sumDeviationXY;
}

void RegressionAnalysis::setB1(QString value) {
    b1 = value;
}

void RegressionAnalysis::setB0(QString value) {
    b0 = value;
}

QString RegressionAnalysis::getB0() {
    return b0;
}

QString RegressionAnalysis::getB1() {
    return b1;
}

QString RegressionAnalysis::getYfromEquation(QString X) {
    //equation is Y = B0 + B1*X
    QDateTime constant = QDateTime::fromString(stock->fileData.at(0).value("time"), "yyyy-MM-dd HH:mm:ss");
    QDateTime current  = QDateTime::fromString(X, "yyyy-MM-dd HH:mm:ss");
    QTime time(0, 0, 0, 0);
    constant.setTime(time);
    double y;
    y = this->getB0().toDouble() + this->getB1().toDouble() * (current.toMSecsSinceEpoch() - constant.toMSecsSinceEpoch());
    return QString::number(y);

}
